package com.mvc.cms.action.admin;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.mvc.cms.entity.main.CmsUser;
import com.mvc.cms.manager.main.CmsUserMng;
import com.mvc.cms.web.WebErrors;
import com.mvc.common.security.encoder.PwdEncoder;
import com.mvc.common.session.SessionProvider;
import com.mvc.common.web.CookieUtils;
import com.mvc.common.web.RequestUtils;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

@Controller
public class CmsLoginAct {
	
	private static final Logger log = LoggerFactory
	        .getLogger(CmsLoginAct.class);
	
	public static final String PROCESS_URL = "processUrl";
	public static final String RETURN_URL = "returnUrl";
	public static final String MESSAGE = "message";
	
	@RequestMapping(value = "/login.do", method = RequestMethod.GET)
	public String input(HttpServletRequest request,
			HttpServletResponse response, ModelMap model) {
		String processUrl = RequestUtils.getQueryParam(request, PROCESS_URL);
		String returnUrl = RequestUtils.getQueryParam(request, RETURN_URL);
		String message = RequestUtils.getQueryParam(request, MESSAGE);
		if (!StringUtils.isBlank(processUrl)) {
			model.addAttribute(PROCESS_URL, processUrl);
		}
		if (!StringUtils.isBlank(returnUrl)) {
			model.addAttribute(RETURN_URL, returnUrl);
		}
		if (!StringUtils.isBlank(message)) {
			model.addAttribute(MESSAGE, message);
		}
		return "login";
	}
	
	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String submit(String username, String password, String captcha,
			String processUrl, String returnUrl, String message,
			HttpServletRequest request, HttpServletResponse response,
			ModelMap model) {
			WebErrors errors = validateSubmit(username, password, captcha
					   , request, response);
			if(!errors.hasErrors()){
				CmsUser cmsUser = cmsUserMng.findByUsername(username);
				if(cmsUser != null){
					if(pwdEncoder.isPasswordValid(cmsUser.getPassword(), password)){
						session.setAttribute(request, response, "adminId", cmsUser.getId());
						String ip = RequestUtils.getIpAddr(request);
						cmsUserMng.updateLoginInfo(cmsUser.getId(), ip);
					    this.removeCookieErrorRemaining(request, response);
						String view = getView(processUrl, returnUrl);
						if (view != null) {
							return view;
						} else {
							String sessionid  = session.getSessionId(request, response);
							return "redirect:index.do?jsession="+sessionid;
						}
					}
				}
			}
			// 登陆失败
			this.writeCookieErrorRemaining(request, response, model);
			if (!StringUtils.isBlank(processUrl)) {
				model.addAttribute(PROCESS_URL, processUrl);
			}
			if (!StringUtils.isBlank(returnUrl)) {
				model.addAttribute(RETURN_URL, returnUrl);
			}
			if (!StringUtils.isBlank(message)) {
				model.addAttribute(MESSAGE, message);
			}
			return "login";
	}
	
	@RequestMapping(value = "/logout.do")
	public String logout(HttpServletRequest request,
			HttpServletResponse response) {
	    session.logout(request, response);
		String processUrl = RequestUtils.getQueryParam(request, "processUrl");
		String returnUrl = RequestUtils.getQueryParam(request, "returnUrl");
		String view = getView(processUrl, returnUrl);
		if (view != null) {
			return view;
		} else {
			return "redirect:index.do";
		}
	}
	
	private WebErrors validateSubmit(String username, String password,
			String captcha, HttpServletRequest request,
			HttpServletResponse response) {
		WebErrors errors = WebErrors.create(request);
		if (errors.ifOutOfLength(username, "username", 1, 100)) {
			return errors;
		}
		if (errors.ifOutOfLength(password, "password", 1, 32)) {
			return errors;
		}
		// 如果输入了验证码，那么必须验证；如果没有输入验证码，则根据当前用户判断是否需要验证码。
		if (!StringUtils.isBlank(captcha)) {
			if (errors.ifBlank(captcha, "captcha", 100)) {
				return errors;
			}
			try {
				if (!imageCaptchaService.validateResponseForID(session
						.getSessionId(request, response), captcha)) {
					errors.addErrorCode("error.invalidCaptcha");
					return errors;
				}
			} catch (CaptchaServiceException e) {
				errors.addErrorCode("error.exceptionCaptcha");
				log.warn("", e);
				return errors;
			}
		}
		return errors;
	}

	/**
	 * 获得地址
	 * @param processUrl
	 * @param returnUrl
	 * @param authId
	 * @param defaultUrl
	 * @return
	 */
	private String getView(String processUrl, String returnUrl) {
		if (!StringUtils.isBlank(processUrl)) {
			StringBuilder sb = new StringBuilder("redirect:");
			sb.append(processUrl).append("?");
			if (!StringUtils.isBlank(returnUrl)) {
				sb.append("&").append("returnUrl").append("=").append(returnUrl);
			}
			return sb.toString();
		} else if (!StringUtils.isBlank(returnUrl)) {
			StringBuilder sb = new StringBuilder("redirect:");
			sb.append(returnUrl);
			return sb.toString();
		} else {
			return null;
		}
	}
	
	private void writeCookieErrorRemaining(HttpServletRequest request, 
			HttpServletResponse response,ModelMap model) {
		// 所有访问的页面都需要写一个cookie，这样可以判断已经登录了几次。
		Integer errorRemaining = getCookieErrorRemaining(request, response);
		System.out.println("上一次错误次数:"+errorRemaining);
		Integer errorInterval = 20;//cookie间隔时间默认20分钟
		int maxErrorTimes = 3;//默认三次登陆错误就输入验证码
		if (errorRemaining == null || errorRemaining > maxErrorTimes) {
			errorRemaining = maxErrorTimes;
		} else if (errorRemaining <= 0) {
			errorRemaining = 0;
		} else {
			errorRemaining--;
		}
		model.addAttribute("errorRemaining", errorRemaining);
		CookieUtils.addCookie(request, response, "_error_remaining",
				errorRemaining.toString(), errorInterval * 60, null);
	}

	private void removeCookieErrorRemaining(HttpServletRequest request,
			HttpServletResponse response) {
		CookieUtils.cancleCookie(request, response, "_error_remaining",
				null);
	}

	private Integer getCookieErrorRemaining(HttpServletRequest request,
			HttpServletResponse response) {
		Cookie cookie = CookieUtils.getCookie(request, "_error_remaining");
		if (cookie != null) {
			String value = cookie.getValue();
			if (NumberUtils.isDigits(value)) {
				return Integer.parseInt(value);
			}
		}
		return null;
	}
	
	@Autowired
	private CmsUserMng cmsUserMng;
	//密码加密
    @Autowired
    private PwdEncoder pwdEncoder;
    //获取session
    @Autowired
    private SessionProvider session;
	@Autowired
	private ImageCaptchaService imageCaptchaService;
}
